package com.frinder.demo5;

import akka.actor.*;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.Procedure;
import com.typesafe.config.ConfigFactory;

/**
 * Created by frinder on 2017/7/25.
 */
public class ProcedureTest extends UntypedActor {

    final LoggingAdapter logger = Logging.getLogger(getContext().system(), this);

    public enum Msg {
        PLAY, SLEEP
    }

    private Procedure<Object> getHappy() {
        return (o) -> {
            logger.info("getHappy: {} {}.", o, hashCode());
            if (o == Msg.PLAY) {
                logger.info("getHappy: Play make me happy.");
                getSender().tell("getHappy: I am happy.", getSelf());
            } else if (o == Msg.SLEEP) {
                logger.info("getHappy: Sleep make me angry.");
                getContext().become(getAngry());
            } else {
                unhandled(o);
            }
        };
    }

    private Procedure<Object> getAngry() {
        return (o) -> {
            logger.info("getAngry: {} {}.", o, hashCode());
            if (o == Msg.PLAY) {
                logger.info("getAngry: Play make me happy.");
                getContext().become(getHappy());
            } else if (o == Msg.SLEEP) {
                logger.info("getAngry: I am angry.");
                getSender().tell("getAngry: Sleep make me angry.", getSelf());
            } else {
                unhandled(o);
            }
        };
    }


    @Override
    public void onReceive(Object o) throws Exception {
        logger.info("onReceive: {} {}.", o, hashCode());
        if (o == Msg.PLAY) {
            getContext().become(getHappy());
        } else if (o == Msg.SLEEP) {
            getContext().become(getAngry());
        } else {
            logger.error("error.");
            unhandled(o);
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ActorSystem system = ActorSystem.create("procedure", ConfigFactory.load("akka.config"));
        ActorRef ref = system.actorOf(Props.create(ProcedureTest.class), "procedure");

        ref.tell(Msg.PLAY, ActorRef.noSender()); // 第一条进 onReceive，但不会处理
        ref.tell(Msg.SLEEP, ActorRef.noSender());
        ref.tell(Msg.PLAY, ActorRef.noSender());
        ref.tell(Msg.PLAY, ActorRef.noSender());

        ref.tell(PoisonPill.getInstance(), ActorRef.noSender());
    }

}
